#include <cassert>
#include <cerrno>


#if defined(WIN32) 
#  include <windows.h>
#  include <winbase.h>
#else
#  include <pthread.h>
#endif
#include "recursive_mutex.hpp"
using namespace vpm::utils;

#if defined(__INTEL_COMPILER)
// !rk! hack, I'm not sure off hand why the Intel compiler can't find this
extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
__THROW;
#endif


#if defined( __APPLE__ )  || defined (__INTEL_COMPILER)
// !cj! need to write apple/intel mutex stuff 

	RecursiveMutex::RecursiveMutex()
	{
		//assert(0); 
	}


	RecursiveMutex::~RecursiveMutex ()
	{
		//assert(0);
	}


	void
		RecursiveMutex::lock()
	{
		//assert(0); 
	}

	void
		RecursiveMutex::unlock()
	{
		//assert(0); 
	}


#else

	RecursiveMutex::RecursiveMutex()
	{
#ifndef WIN32
		int rc = pthread_mutexattr_init(&mMutexAttr);
#if defined(__linux__)
		pthread_mutexattr_settype(&mMutexAttr, PTHREAD_MUTEX_RECURSIVE_NP);
#else
		pthread_mutexattr_settype(&mMutexAttr, PTHREAD_MUTEX_RECURSIVE);
#endif

		rc = pthread_mutex_init(&mId, &mMutexAttr);
		assert( rc == 0 );
#else
		InitializeCriticalSection(&mId);
#endif
	}


	RecursiveMutex::~RecursiveMutex ()
	{
#ifndef WIN32
		int  rc = pthread_mutex_destroy(&mId);
		assert( rc != EBUSY );  // currently locked 
		assert( rc == 0 );
		rc = pthread_mutexattr_destroy(&mMutexAttr);
#else
		DeleteCriticalSection(&mId);
#endif
	}


	void RecursiveMutex::lock()
	{
#ifndef WIN32
		int  rc = pthread_mutex_lock(&mId);
		assert( rc != EINVAL );
		assert( rc != EDEADLK );
		assert( rc == 0 );
#else
		EnterCriticalSection(&mId);
#endif
	}

	void RecursiveMutex::unlock()
	{
#ifndef WIN32
		int  rc = pthread_mutex_unlock(&mId);
		assert( rc != EINVAL );
		assert( rc != EPERM );
		assert( rc == 0 );
#else
		LeaveCriticalSection(&mId);
#endif
	}

#ifndef WIN32
	pthread_mutex_t*
		RecursiveMutex::getId() const
	{
		return ( &mId );
	}
#endif

#endif
